`timescale 1ns / 1ps

`include "data_width.vh"

module rd_src_p_shuffle_block_3 #(parameter
    VERTEX_PIPE_NUM     = `VERTEX_PIPE_NUM,
    EDGE_PIPE_NUM       = `EDGE_PIPE_NUM,
    VERTEX_BRAM_NUM     = `VERTEX_BRAM_NUM,
    VERTEX_BRAM_AWIDTH  = `VERTEX_BRAM_AWIDTH,
    VERTEX_MASK_WIDTH   = `VERTEX_MASK_WIDTH,
    REQ_WIDTH           = `REQ_WIDTH,
    SRC_P_AWIDTH        = `SRC_P_AWIDTH,
    DST_ID_DWIDTH       = `DST_ID_DWIDTH,
    TOT_EDGE_MASK_WIDTH = `TOT_EDGE_MASK_WIDTH,
    TOT_ACC_ID_WIDTH    = `TOT_ACC_ID_WIDTH,
    REORDER_LOC_Y_WIDTH = `REORDER_LOC_Y_WIDTH
    ) (
        input                                                   clk,
        input                                                   front_rst,
        input [SRC_P_AWIDTH * EDGE_PIPE_NUM - 1 : 0]            front_rd_src_p_addr,
        input [REQ_WIDTH - 1 : 0]                               front_req_num,
        input                                                   front_rd_src_p_valid,
        input [TOT_EDGE_MASK_WIDTH - 1 : 0]                     front_tot_src_p_mask,
        input [TOT_ACC_ID_WIDTH - 1 : 0]                        front_tot_acc_id,
        input                                                   front_any_dst_data_valid,
        input [DST_ID_DWIDTH * VERTEX_PIPE_NUM - 1 : 0]         front_dst_id,
        input [VERTEX_MASK_WIDTH * VERTEX_PIPE_NUM - 1 : 0]     front_src_p_mask_r,
        input [VERTEX_PIPE_NUM - 1 : 0]                         front_dst_data_valid,
        input                                                   back_stage_vertex_full,

        output                                                  rst,
        output                                                  buffer_full_edge,
        output                                                  buffer_full_vertex,
        output                                                  rd_src_p_addr_finish,
        output [VERTEX_BRAM_AWIDTH * VERTEX_BRAM_NUM - 1 : 0]   rd_src_p_addr,
        output [REORDER_LOC_Y_WIDTH * VERTEX_BRAM_NUM - 1 : 0]  reorder_loc_y,
        output [VERTEX_BRAM_NUM - 1 : 0]                        rd_src_p_valid,
        output [TOT_EDGE_MASK_WIDTH - 1 : 0]                    tot_src_p_mask,
        output [TOT_ACC_ID_WIDTH - 1 : 0]                       tot_acc_id,
        output                                                  any_dst_data_valid,
        output [DST_ID_DWIDTH * VERTEX_PIPE_NUM - 1 : 0]        dst_id,
        output [VERTEX_MASK_WIDTH * VERTEX_PIPE_NUM - 1 : 0]    src_p_mask_r,
        output [VERTEX_PIPE_NUM - 1 : 0]                        dst_data_valid);

    wire                            edge_buffer_empty, edge_buffer_full;
    wire [VERTEX_PIPE_NUM - 1 : 0]  dst_buffer_empty, dst_buffer_full;
    wire                            mask_buffer_empty, mask_buffer_full;
    wire [VERTEX_PIPE_NUM - 1 : 0]  data_valid;

    assign buffer_full_edge     = edge_buffer_full;
    assign buffer_full_vertex   = dst_buffer_full[0];
    assign any_dst_data_valid   = data_valid[0];

    rd_src_p_shuffle_block_3_para_trans P (
        .clk(clk), .front_rst(front_rst),

        .rst(rst));

    rd_src_p_shuffle_block_3_edge E1 (
        .clk(clk), .rst(front_rst),
        .front_rd_src_p_addr(front_rd_src_p_addr), .front_rd_src_p_valid(front_rd_src_p_valid),
        .front_req_num(front_req_num),

        .buffer_empty(edge_buffer_empty), .buffer_full(edge_buffer_full),
        .rd_src_p_addr_finish(rd_src_p_addr_finish),
        .rd_src_p_addr(rd_src_p_addr), .reorder_loc_y(reorder_loc_y), .rd_src_p_valid(rd_src_p_valid));

    rd_src_p_shuffle_block_3_mask M1 (
        .clk(clk), .rst(front_rst),
        .front_tot_src_p_mask(front_tot_src_p_mask), .front_tot_acc_id(front_tot_acc_id),
        .front_any_dst_data_valid(front_any_dst_data_valid), .back_stage_vertex_full(back_stage_vertex_full),

        .buffer_empty(mask_buffer_empty), .buffer_full(mask_buffer_full),
        .tot_src_p_mask(tot_src_p_mask), .tot_acc_id(tot_acc_id));

    generate
        genvar i;
        for (i = 0; i < VERTEX_PIPE_NUM; i = i + 1) begin : M9_3_BLOCK_1
            rd_src_p_shuffle_block_3_vertex_single V (
                .clk                        (clk),
                .rst                        (front_rst),
                .front_dst_id               (front_dst_id[(i + 1) * DST_ID_DWIDTH - 1 : i * DST_ID_DWIDTH]),
                .front_src_p_mask_r         (front_src_p_mask_r[(i + 1) * VERTEX_MASK_WIDTH - 1 : i * VERTEX_MASK_WIDTH]),
                .front_dst_data_valid       (front_dst_data_valid[i]),
                .front_any_dst_data_valid   (front_any_dst_data_valid), .back_stage_vertex_full(back_stage_vertex_full),

                .buffer_empty               (dst_buffer_empty[i]),
                .buffer_full                (dst_buffer_full[i]),
                .data_valid                 (data_valid[i]),
                .dst_id                     (dst_id[(i + 1) * DST_ID_DWIDTH - 1 : i * DST_ID_DWIDTH]),
                .src_p_mask_r               (src_p_mask_r[(i + 1) * VERTEX_MASK_WIDTH - 1 : i * VERTEX_MASK_WIDTH]),
                .dst_data_valid             (dst_data_valid[i]));
        end
    endgenerate

endmodule

module rd_src_p_shuffle_block_3_para_trans (
    input       clk,
    input       front_rst,

    output reg  rst);
    
    always @ (posedge clk) begin
        rst <= front_rst;
    end

endmodule

module rd_src_p_shuffle_block_3_edge #(parameter
    SRC_P_AWIDTH            = `SRC_P_AWIDTH,
    REQ_WIDTH               = `REQ_WIDTH,
    REORDER_LOC_Y_WIDTH     = `REORDER_LOC_Y_WIDTH,
    VERTEX_PIPE_NUM         = `VERTEX_PIPE_NUM,
    EDGE_PIPE_NUM           = `EDGE_PIPE_NUM,
    VERTEX_BRAM_NUM         = `VERTEX_BRAM_NUM,
    VERTEX_BRAM_AWIDTH      = `VERTEX_BRAM_AWIDTH,
    VERTEX_BRAM_NUM_WIDTH   = `VERTEX_BRAM_NUM_WIDTH
    ) (
        input                                                   clk,
        input                                                   rst,
        input [SRC_P_AWIDTH * EDGE_PIPE_NUM - 1 : 0]            front_rd_src_p_addr,
        input [REQ_WIDTH - 1 : 0]                               front_req_num,
        input                                                   front_rd_src_p_valid,

        output                                                  buffer_empty,
        output                                                  buffer_full,
        output reg                                              rd_src_p_addr_finish,
        output [VERTEX_BRAM_AWIDTH * VERTEX_BRAM_NUM - 1 : 0]   rd_src_p_addr,
        output [REORDER_LOC_Y_WIDTH * VERTEX_BRAM_NUM - 1 : 0]  reorder_loc_y,
        output [VERTEX_BRAM_NUM - 1 : 0]                        rd_src_p_valid);

    reg [REQ_WIDTH - 1 : 0]                     now_req_num;

    wire [REQ_WIDTH - 1 : 0]                    top_req_num;
    wire [(VERTEX_BRAM_AWIDTH + VERTEX_BRAM_NUM_WIDTH) * EDGE_PIPE_NUM - 1 : 0] top_rd_src_p_addr;
    wire [EDGE_PIPE_NUM - 1 : 0]                top_rd_src_p_valid;
    wire [EDGE_PIPE_NUM - 1 : 0]                buffer_empty_tmp;
    wire [EDGE_PIPE_NUM - 1 : 0]                buffer_full_tmp;

    generate
        genvar i;
        for (i = 0; i < EDGE_PIPE_NUM; i = i + 1) begin : M9_3_BLOCK
        // change SRC_P_AWIDTH to VERTEX_BRAM_AWIDTH + VERTEX_BRAM_NUM_WIDTH, make fanout lowwer.
            bram_addr_fifo_fall_through af (
                .clk(clk), .srst(rst),
                .din(front_rd_src_p_addr[i * SRC_P_AWIDTH + VERTEX_BRAM_AWIDTH + VERTEX_BRAM_NUM_WIDTH - 1 : i * SRC_P_AWIDTH]),
                .wr_en(front_rd_src_p_valid), .rd_en(top_req_num == now_req_num),

                .dout(top_rd_src_p_addr[(i + 1) * (VERTEX_BRAM_AWIDTH + VERTEX_BRAM_NUM_WIDTH) - 1 : i * (VERTEX_BRAM_AWIDTH + VERTEX_BRAM_NUM_WIDTH)]),
                .valid(top_rd_src_p_valid[i]),
                .empty(buffer_empty_tmp[i]), .prog_full(buffer_full_tmp[i]));
        end
    endgenerate

    req_num_fifo_fall_through rnf (
        .clk(clk), .srst(rst),
        .din(front_req_num), .wr_en(front_rd_src_p_valid), .rd_en(top_req_num == now_req_num),

        .dout(top_req_num));

    generate
        for (i = 0; i < VERTEX_BRAM_NUM; i = i + 1) begin : M9_3_BLOCK_2
            rd_src_p_shuffle_block_3_edge_single #(.LOC(i)) E (
                .clk(clk), .rst(rst),
                .top_rd_src_p_addr(top_rd_src_p_addr), .top_rd_src_p_valid(top_rd_src_p_valid[0]),
                .shuffle_final(top_req_num == now_req_num),

                .rd_src_p_addr_single(rd_src_p_addr[(i + 1) * VERTEX_BRAM_AWIDTH - 1 : i * VERTEX_BRAM_AWIDTH]),
                .reorder_loc_y_single(reorder_loc_y[(i + 1) * REORDER_LOC_Y_WIDTH - 1 : i * REORDER_LOC_Y_WIDTH]),
                .rd_src_p_valid_single(rd_src_p_valid[i]));
        end
    endgenerate

    assign buffer_empty = buffer_empty_tmp[0];
    assign buffer_full = buffer_full_tmp[0];

    // reuse信号和finish信号同步传递
    always @ (posedge clk) begin
        if (rst) begin
            now_req_num <= 1;
            rd_src_p_addr_finish <= 1'b0;
        end
        else begin
            if (!buffer_empty) begin
                if (top_req_num == now_req_num) begin
                    now_req_num <= 1;
                    rd_src_p_addr_finish <= 1'b1;
                end
                else begin
                    now_req_num <= now_req_num + 1;
                    rd_src_p_addr_finish <= 1'b0;
                end
            end
            else begin
                now_req_num <= 1;
                rd_src_p_addr_finish <= 1'b0;
            end
        end
    end

endmodule

module rd_src_p_shuffle_block_3_edge_single #(parameter
    LOC                     = 6'b000000,
    VERTEX_BRAM_NUM         = `VERTEX_BRAM_NUM,
    VERTEX_BRAM_AWIDTH      = `VERTEX_BRAM_AWIDTH,
    VERTEX_BRAM_NUM_WIDTH   = `VERTEX_BRAM_NUM_WIDTH,
    REORDER_LOC_Y_WIDTH     = `REORDER_LOC_Y_WIDTH,
    EDGE_PIPE_NUM           = `EDGE_PIPE_NUM,
    TOP_RD_SRC_P_ADDR_WIDTH = `VERTEX_BRAM_AWIDTH + `VERTEX_BRAM_NUM_WIDTH
    ) (
        input clk,
        input rst,
        input [(VERTEX_BRAM_AWIDTH + VERTEX_BRAM_NUM_WIDTH) * EDGE_PIPE_NUM - 1 : 0] top_rd_src_p_addr,
        input top_rd_src_p_valid,
        input shuffle_final,

        output reg [VERTEX_BRAM_AWIDTH - 1 : 0] rd_src_p_addr_single,
        output reg [REORDER_LOC_Y_WIDTH - 1 : 0] reorder_loc_y_single,
        output reg rd_src_p_valid_single);

    reg [EDGE_PIPE_NUM - 1 : 0] rd_src_p_addr_nshuffle_valid;

    wire [EDGE_PIPE_NUM - 1 : 0] shuffle_valid_i;
    generate
        genvar i;
        for (i = 0; i < EDGE_PIPE_NUM; i = i + 1) begin : M9_3_BLOCK_3
            assign shuffle_valid_i[i] = (rd_src_p_addr_nshuffle_valid[i] && (top_rd_src_p_addr[i * TOP_RD_SRC_P_ADDR_WIDTH + VERTEX_BRAM_NUM_WIDTH - 1 : i * TOP_RD_SRC_P_ADDR_WIDTH]) == LOC);
        end
    endgenerate

    always @ (posedge clk) begin
        if (rst) begin
            rd_src_p_addr_single <= 0;
            reorder_loc_y_single <= 0;
            rd_src_p_valid_single <= 0;

            rd_src_p_addr_nshuffle_valid <= {EDGE_PIPE_NUM{1'b1}};
        end
        else begin
            casex (shuffle_valid_i)
                32'b00000000000000000000000000000000: begin
                    rd_src_p_addr_single <= 0;
                    reorder_loc_y_single <= 0;
                    rd_src_p_valid_single <= 0;
                    rd_src_p_addr_nshuffle_valid <= {EDGE_PIPE_NUM{1'b1}};
                end
                32'bxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx1: begin
                    rd_src_p_addr_single <= top_rd_src_p_addr[TOP_RD_SRC_P_ADDR_WIDTH - 1 : VERTEX_BRAM_NUM_WIDTH];
                    reorder_loc_y_single <= 5'b00000;
                    rd_src_p_valid_single <= 1'b1;
                    rd_src_p_addr_nshuffle_valid <= shuffle_final ? {EDGE_PIPE_NUM{1'b1}} : (rd_src_p_addr_nshuffle_valid & 32'hfffffffe);
                end
                32'bxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx10: begin
                    rd_src_p_addr_single <= top_rd_src_p_addr[TOP_RD_SRC_P_ADDR_WIDTH * 2 - 1 : TOP_RD_SRC_P_ADDR_WIDTH * 1 + VERTEX_BRAM_NUM_WIDTH];
                    reorder_loc_y_single <= 5'b00001;
                    rd_src_p_valid_single <= 1'b1;
                    rd_src_p_addr_nshuffle_valid <= shuffle_final ? {EDGE_PIPE_NUM{1'b1}} : (rd_src_p_addr_nshuffle_valid & 32'hfffffffd);
                end
                32'bxxxxxxxxxxxxxxxxxxxxxxxxxxxxx100: begin
                    rd_src_p_addr_single <= top_rd_src_p_addr[TOP_RD_SRC_P_ADDR_WIDTH * 3 - 1 : TOP_RD_SRC_P_ADDR_WIDTH * 2 + VERTEX_BRAM_NUM_WIDTH];
                    reorder_loc_y_single <= 5'b00010;
                    rd_src_p_valid_single <= 1'b1;
                    rd_src_p_addr_nshuffle_valid <= shuffle_final ? {EDGE_PIPE_NUM{1'b1}} : (rd_src_p_addr_nshuffle_valid & 32'hfffffffb);
                end
                32'bxxxxxxxxxxxxxxxxxxxxxxxxxxxx1000: begin
                    rd_src_p_addr_single <= top_rd_src_p_addr[TOP_RD_SRC_P_ADDR_WIDTH * 4 - 1 : TOP_RD_SRC_P_ADDR_WIDTH * 3 + VERTEX_BRAM_NUM_WIDTH];
                    reorder_loc_y_single <= 5'b00011;
                    rd_src_p_valid_single <= 1'b1;
                    rd_src_p_addr_nshuffle_valid <= shuffle_final ? {EDGE_PIPE_NUM{1'b1}} : (rd_src_p_addr_nshuffle_valid & 32'hfffffff7);
                end
                32'bxxxxxxxxxxxxxxxxxxxxxxxxxxx10000: begin
                    rd_src_p_addr_single <= top_rd_src_p_addr[TOP_RD_SRC_P_ADDR_WIDTH * 5 - 1 : TOP_RD_SRC_P_ADDR_WIDTH * 4 + VERTEX_BRAM_NUM_WIDTH];
                    reorder_loc_y_single <= 5'b00100;
                    rd_src_p_valid_single <= 1'b1;
                    rd_src_p_addr_nshuffle_valid <= shuffle_final ? {EDGE_PIPE_NUM{1'b1}} : (rd_src_p_addr_nshuffle_valid & 32'hffffffef);
                end
                32'bxxxxxxxxxxxxxxxxxxxxxxxxxx100000: begin
                    rd_src_p_addr_single <= top_rd_src_p_addr[TOP_RD_SRC_P_ADDR_WIDTH * 6 - 1 : TOP_RD_SRC_P_ADDR_WIDTH * 5 + VERTEX_BRAM_NUM_WIDTH];
                    reorder_loc_y_single <= 5'b00101;
                    rd_src_p_valid_single <= 1'b1;
                    rd_src_p_addr_nshuffle_valid <= shuffle_final ? {EDGE_PIPE_NUM{1'b1}} : (rd_src_p_addr_nshuffle_valid & 32'hffffffdf);
                end
                32'bxxxxxxxxxxxxxxxxxxxxxxxxx1000000: begin
                    rd_src_p_addr_single <= top_rd_src_p_addr[TOP_RD_SRC_P_ADDR_WIDTH * 7 - 1 : TOP_RD_SRC_P_ADDR_WIDTH * 6 + VERTEX_BRAM_NUM_WIDTH];
                    reorder_loc_y_single <= 5'b00110;
                    rd_src_p_valid_single <= 1'b1;
                    rd_src_p_addr_nshuffle_valid <= shuffle_final ? {EDGE_PIPE_NUM{1'b1}} : (rd_src_p_addr_nshuffle_valid & 32'hffffffbf);
                end
                32'bxxxxxxxxxxxxxxxxxxxxxxxx10000000: begin
                    rd_src_p_addr_single <= top_rd_src_p_addr[TOP_RD_SRC_P_ADDR_WIDTH * 8 - 1 : TOP_RD_SRC_P_ADDR_WIDTH * 7 + VERTEX_BRAM_NUM_WIDTH];
                    reorder_loc_y_single <= 5'b00111;
                    rd_src_p_valid_single <= 1'b1;
                    rd_src_p_addr_nshuffle_valid <= shuffle_final ? {EDGE_PIPE_NUM{1'b1}} : (rd_src_p_addr_nshuffle_valid & 32'hffffff7f);
                end
                32'bxxxxxxxxxxxxxxxxxxxxxxx100000000: begin
                    rd_src_p_addr_single <= top_rd_src_p_addr[TOP_RD_SRC_P_ADDR_WIDTH * 9 - 1 : TOP_RD_SRC_P_ADDR_WIDTH * 8 + VERTEX_BRAM_NUM_WIDTH];
                    reorder_loc_y_single <= 5'b01000;
                    rd_src_p_valid_single <= 1'b1;
                    rd_src_p_addr_nshuffle_valid <= shuffle_final ? {EDGE_PIPE_NUM{1'b1}} : (rd_src_p_addr_nshuffle_valid & 32'hfffffeff);
                end
                32'bxxxxxxxxxxxxxxxxxxxxxx1000000000: begin
                    rd_src_p_addr_single <= top_rd_src_p_addr[TOP_RD_SRC_P_ADDR_WIDTH * 10 - 1 : TOP_RD_SRC_P_ADDR_WIDTH * 9 + VERTEX_BRAM_NUM_WIDTH];
                    reorder_loc_y_single <= 5'b01001;
                    rd_src_p_valid_single <= 1'b1;
                    rd_src_p_addr_nshuffle_valid <= shuffle_final ? {EDGE_PIPE_NUM{1'b1}} : (rd_src_p_addr_nshuffle_valid & 32'hfffffdff);
                end
                32'bxxxxxxxxxxxxxxxxxxxxx10000000000: begin
                    rd_src_p_addr_single <= top_rd_src_p_addr[TOP_RD_SRC_P_ADDR_WIDTH * 11 - 1 : TOP_RD_SRC_P_ADDR_WIDTH * 10 + VERTEX_BRAM_NUM_WIDTH];
                    reorder_loc_y_single <= 5'b01010;
                    rd_src_p_valid_single <= 1'b1;
                    rd_src_p_addr_nshuffle_valid <= shuffle_final ? {EDGE_PIPE_NUM{1'b1}} : (rd_src_p_addr_nshuffle_valid & 32'hfffffbff);
                end
                32'bxxxxxxxxxxxxxxxxxxxx100000000000: begin
                    rd_src_p_addr_single <= top_rd_src_p_addr[TOP_RD_SRC_P_ADDR_WIDTH * 12 - 1 : TOP_RD_SRC_P_ADDR_WIDTH * 11 + VERTEX_BRAM_NUM_WIDTH];
                    reorder_loc_y_single <= 5'b01011;
                    rd_src_p_valid_single <= 1'b1;
                    rd_src_p_addr_nshuffle_valid <= shuffle_final ? {EDGE_PIPE_NUM{1'b1}} : (rd_src_p_addr_nshuffle_valid & 32'hfffff7ff);
                end
                32'bxxxxxxxxxxxxxxxxxxx1000000000000: begin
                    rd_src_p_addr_single <= top_rd_src_p_addr[TOP_RD_SRC_P_ADDR_WIDTH * 13 - 1 : TOP_RD_SRC_P_ADDR_WIDTH * 12 + VERTEX_BRAM_NUM_WIDTH];
                    reorder_loc_y_single <= 5'b01100;
                    rd_src_p_valid_single <= 1'b1;
                    rd_src_p_addr_nshuffle_valid <= shuffle_final ? {EDGE_PIPE_NUM{1'b1}} : (rd_src_p_addr_nshuffle_valid & 32'hffffefff);
                end
                32'bxxxxxxxxxxxxxxxxxx10000000000000: begin
                    rd_src_p_addr_single <= top_rd_src_p_addr[TOP_RD_SRC_P_ADDR_WIDTH * 14 - 1 : TOP_RD_SRC_P_ADDR_WIDTH * 13 + VERTEX_BRAM_NUM_WIDTH];
                    reorder_loc_y_single <= 5'b01101;
                    rd_src_p_valid_single <= 1'b1;
                    rd_src_p_addr_nshuffle_valid <= shuffle_final ? {EDGE_PIPE_NUM{1'b1}} : (rd_src_p_addr_nshuffle_valid & 32'hffffdfff);
                end
                32'bxxxxxxxxxxxxxxxxx100000000000000: begin
                    rd_src_p_addr_single <= top_rd_src_p_addr[TOP_RD_SRC_P_ADDR_WIDTH * 15 - 1 : TOP_RD_SRC_P_ADDR_WIDTH * 14 + VERTEX_BRAM_NUM_WIDTH];
                    reorder_loc_y_single <= 5'b01110;
                    rd_src_p_valid_single <= 1'b1;
                    rd_src_p_addr_nshuffle_valid <= shuffle_final ? {EDGE_PIPE_NUM{1'b1}} : (rd_src_p_addr_nshuffle_valid & 32'hffffbfff);
                end
                32'bxxxxxxxxxxxxxxxx1000000000000000: begin
                    rd_src_p_addr_single <= top_rd_src_p_addr[TOP_RD_SRC_P_ADDR_WIDTH * 16 - 1 : TOP_RD_SRC_P_ADDR_WIDTH * 15 + VERTEX_BRAM_NUM_WIDTH];
                    reorder_loc_y_single <= 5'b01111;
                    rd_src_p_valid_single <= 1'b1;
                    rd_src_p_addr_nshuffle_valid <= shuffle_final ? {EDGE_PIPE_NUM{1'b1}} : (rd_src_p_addr_nshuffle_valid & 32'hffff7fff);
                end
                32'bxxxxxxxxxxxxxxx10000000000000000: begin
                    rd_src_p_addr_single <= top_rd_src_p_addr[TOP_RD_SRC_P_ADDR_WIDTH * 17 - 1 : TOP_RD_SRC_P_ADDR_WIDTH * 16 + VERTEX_BRAM_NUM_WIDTH];
                    reorder_loc_y_single <= 5'b10000;
                    rd_src_p_valid_single <= 1'b1;
                    rd_src_p_addr_nshuffle_valid <= shuffle_final ? {EDGE_PIPE_NUM{1'b1}} : (rd_src_p_addr_nshuffle_valid & 32'hfffeffff);
                end
                32'bxxxxxxxxxxxxxx100000000000000000: begin
                    rd_src_p_addr_single <= top_rd_src_p_addr[TOP_RD_SRC_P_ADDR_WIDTH * 18 - 1 : TOP_RD_SRC_P_ADDR_WIDTH * 17 + VERTEX_BRAM_NUM_WIDTH];
                    reorder_loc_y_single <= 5'b10001;
                    rd_src_p_valid_single <= 1'b1;
                    rd_src_p_addr_nshuffle_valid <= shuffle_final ? {EDGE_PIPE_NUM{1'b1}} : (rd_src_p_addr_nshuffle_valid & 32'hfffdffff);
                end
                32'bxxxxxxxxxxxxx1000000000000000000: begin
                    rd_src_p_addr_single <= top_rd_src_p_addr[TOP_RD_SRC_P_ADDR_WIDTH * 19 - 1 : TOP_RD_SRC_P_ADDR_WIDTH * 18 + VERTEX_BRAM_NUM_WIDTH];
                    reorder_loc_y_single <= 5'b10010;
                    rd_src_p_valid_single <= 1'b1;
                    rd_src_p_addr_nshuffle_valid <= shuffle_final ? {EDGE_PIPE_NUM{1'b1}} : (rd_src_p_addr_nshuffle_valid & 32'hfffbffff);
                end
                32'bxxxxxxxxxxxx10000000000000000000: begin
                    rd_src_p_addr_single <= top_rd_src_p_addr[TOP_RD_SRC_P_ADDR_WIDTH * 20 - 1 : TOP_RD_SRC_P_ADDR_WIDTH * 19 + VERTEX_BRAM_NUM_WIDTH];
                    reorder_loc_y_single <= 5'b10011;
                    rd_src_p_valid_single <= 1'b1;
                    rd_src_p_addr_nshuffle_valid <= shuffle_final ? {EDGE_PIPE_NUM{1'b1}} : (rd_src_p_addr_nshuffle_valid & 32'hfff7ffff);
                end
                32'bxxxxxxxxxxx100000000000000000000: begin
                    rd_src_p_addr_single <= top_rd_src_p_addr[TOP_RD_SRC_P_ADDR_WIDTH * 21 - 1 : TOP_RD_SRC_P_ADDR_WIDTH * 20 + VERTEX_BRAM_NUM_WIDTH];
                    reorder_loc_y_single <= 5'b10100;
                    rd_src_p_valid_single <= 1'b1;
                    rd_src_p_addr_nshuffle_valid <= shuffle_final ? {EDGE_PIPE_NUM{1'b1}} : (rd_src_p_addr_nshuffle_valid & 32'hffefffff);
                end
                32'bxxxxxxxxxx1000000000000000000000: begin
                    rd_src_p_addr_single <= top_rd_src_p_addr[TOP_RD_SRC_P_ADDR_WIDTH * 22 - 1 : TOP_RD_SRC_P_ADDR_WIDTH * 21 + VERTEX_BRAM_NUM_WIDTH];
                    reorder_loc_y_single <= 5'b10101;
                    rd_src_p_valid_single <= 1'b1;
                    rd_src_p_addr_nshuffle_valid <= shuffle_final ? {EDGE_PIPE_NUM{1'b1}} : (rd_src_p_addr_nshuffle_valid & 32'hffdfffff);
                end
                32'bxxxxxxxxx10000000000000000000000: begin
                    rd_src_p_addr_single <= top_rd_src_p_addr[TOP_RD_SRC_P_ADDR_WIDTH * 23 - 1 : TOP_RD_SRC_P_ADDR_WIDTH * 22 + VERTEX_BRAM_NUM_WIDTH];
                    reorder_loc_y_single <= 5'b10110;
                    rd_src_p_valid_single <= 1'b1;
                    rd_src_p_addr_nshuffle_valid <= shuffle_final ? {EDGE_PIPE_NUM{1'b1}} : (rd_src_p_addr_nshuffle_valid & 32'hffbfffff);
                end
                32'bxxxxxxxx100000000000000000000000: begin
                    rd_src_p_addr_single <= top_rd_src_p_addr[TOP_RD_SRC_P_ADDR_WIDTH * 24 - 1 : TOP_RD_SRC_P_ADDR_WIDTH * 23 + VERTEX_BRAM_NUM_WIDTH];
                    reorder_loc_y_single <= 5'b10111;
                    rd_src_p_valid_single <= 1'b1;
                    rd_src_p_addr_nshuffle_valid <= shuffle_final ? {EDGE_PIPE_NUM{1'b1}} : (rd_src_p_addr_nshuffle_valid & 32'hff7fffff);
                end
                32'bxxxxxxx1000000000000000000000000: begin
                    rd_src_p_addr_single <= top_rd_src_p_addr[TOP_RD_SRC_P_ADDR_WIDTH * 25 - 1 : TOP_RD_SRC_P_ADDR_WIDTH * 24 + VERTEX_BRAM_NUM_WIDTH];
                    reorder_loc_y_single <= 6'b011000;
                    rd_src_p_valid_single <= 1'b1;
                    rd_src_p_addr_nshuffle_valid <= shuffle_final ? {EDGE_PIPE_NUM{1'b1}} : (rd_src_p_addr_nshuffle_valid & 32'hfeffffff);
                end
                32'bxxxxxx10000000000000000000000000: begin
                    rd_src_p_addr_single <= top_rd_src_p_addr[TOP_RD_SRC_P_ADDR_WIDTH * 26 - 1 : TOP_RD_SRC_P_ADDR_WIDTH * 25 + VERTEX_BRAM_NUM_WIDTH];
                    reorder_loc_y_single <= 5'b11001;
                    rd_src_p_valid_single <= 1'b1;
                    rd_src_p_addr_nshuffle_valid <= shuffle_final ? {EDGE_PIPE_NUM{1'b1}} : (rd_src_p_addr_nshuffle_valid & 32'hfdffffff);
                end
                32'bxxxxx100000000000000000000000000: begin
                    rd_src_p_addr_single <= top_rd_src_p_addr[TOP_RD_SRC_P_ADDR_WIDTH * 27 - 1 : TOP_RD_SRC_P_ADDR_WIDTH * 26 + VERTEX_BRAM_NUM_WIDTH];
                    reorder_loc_y_single <= 5'b11010;
                    rd_src_p_valid_single <= 1'b1;
                    rd_src_p_addr_nshuffle_valid <= shuffle_final ? {EDGE_PIPE_NUM{1'b1}} : (rd_src_p_addr_nshuffle_valid & 32'hfbffffff);
                end
                32'bxxxx1000000000000000000000000000: begin
                    rd_src_p_addr_single <= top_rd_src_p_addr[TOP_RD_SRC_P_ADDR_WIDTH * 28 - 1 : TOP_RD_SRC_P_ADDR_WIDTH * 27 + VERTEX_BRAM_NUM_WIDTH];
                    reorder_loc_y_single <= 5'b11011;
                    rd_src_p_valid_single <= 1'b1;
                    rd_src_p_addr_nshuffle_valid <= shuffle_final ? {EDGE_PIPE_NUM{1'b1}} : (rd_src_p_addr_nshuffle_valid & 32'hf7ffffff);
                end
                32'bxxx10000000000000000000000000000: begin
                    rd_src_p_addr_single <= top_rd_src_p_addr[TOP_RD_SRC_P_ADDR_WIDTH * 29 - 1 : TOP_RD_SRC_P_ADDR_WIDTH * 28 + VERTEX_BRAM_NUM_WIDTH];
                    reorder_loc_y_single <= 5'b11100;
                    rd_src_p_valid_single <= 1'b1;
                    rd_src_p_addr_nshuffle_valid <= shuffle_final ? {EDGE_PIPE_NUM{1'b1}} : (rd_src_p_addr_nshuffle_valid & 32'hefffffff);
                end
                32'bxx100000000000000000000000000000: begin
                    rd_src_p_addr_single <= top_rd_src_p_addr[TOP_RD_SRC_P_ADDR_WIDTH * 30 - 1 : TOP_RD_SRC_P_ADDR_WIDTH * 29 + VERTEX_BRAM_NUM_WIDTH];
                    reorder_loc_y_single <= 5'b11101;
                    rd_src_p_valid_single <= 1'b1;
                    rd_src_p_addr_nshuffle_valid <= shuffle_final ? {EDGE_PIPE_NUM{1'b1}} : (rd_src_p_addr_nshuffle_valid & 32'hdfffffff);
                end
                32'bx1000000000000000000000000000000: begin
                    rd_src_p_addr_single <= top_rd_src_p_addr[TOP_RD_SRC_P_ADDR_WIDTH * 31 - 1 : TOP_RD_SRC_P_ADDR_WIDTH * 30 + VERTEX_BRAM_NUM_WIDTH];
                    reorder_loc_y_single <= 5'b11110;
                    rd_src_p_valid_single <= 1'b1;
                    rd_src_p_addr_nshuffle_valid <= shuffle_final ? {EDGE_PIPE_NUM{1'b1}} : (rd_src_p_addr_nshuffle_valid & 32'hbfffffff);
                end
                32'b10000000000000000000000000000000: begin
                    rd_src_p_addr_single <= top_rd_src_p_addr[TOP_RD_SRC_P_ADDR_WIDTH * 32 - 1 : TOP_RD_SRC_P_ADDR_WIDTH * 31 + VERTEX_BRAM_NUM_WIDTH];
                    reorder_loc_y_single <= 5'b11111;
                    rd_src_p_valid_single <= 1'b1;
                    rd_src_p_addr_nshuffle_valid <= shuffle_final ? {EDGE_PIPE_NUM{1'b1}} : (rd_src_p_addr_nshuffle_valid & 32'h7fffffff);
                end
            endcase
        end
    end

endmodule

module rd_src_p_shuffle_block_3_mask #(parameter
    TOT_EDGE_MASK_WIDTH = `TOT_EDGE_MASK_WIDTH, TOT_ACC_ID_WIDTH = `TOT_ACC_ID_WIDTH
    ) (
        input                                   clk,
        input                                   rst,
        input [TOT_EDGE_MASK_WIDTH - 1 : 0]     front_tot_src_p_mask,
        input [TOT_ACC_ID_WIDTH - 1 : 0]        front_tot_acc_id,
        input                                   front_any_dst_data_valid,
        input                                   back_stage_vertex_full,

        output                                  buffer_empty,
        output                                  buffer_full,
        output [TOT_EDGE_MASK_WIDTH - 1 : 0]    tot_src_p_mask,
        output [TOT_ACC_ID_WIDTH - 1 : 0]       tot_acc_id);

    tot_edge_mask_fifo TEM1 (
        .clk(clk), .srst(rst),
        .din(front_tot_src_p_mask), .wr_en(front_any_dst_data_valid), .rd_en(!back_stage_vertex_full),

        .dout(tot_src_p_mask), .empty(buffer_empty), .prog_full(buffer_full));

    tot_acc_id_fifo TAI1 (
        .clk(clk), .srst(rst),
        .din(front_tot_acc_id), .wr_en(front_any_dst_data_valid), .rd_en(!back_stage_vertex_full),

        .dout(tot_acc_id));

endmodule

module rd_src_p_shuffle_block_3_vertex_single #(parameter
    DST_ID_DWIDTH = `DST_ID_DWIDTH, VERTEX_MASK_WIDTH = `VERTEX_MASK_WIDTH
    ) (
        input                                   clk,
        input                                   rst,
        input [DST_ID_DWIDTH - 1 : 0]           front_dst_id,
        input [VERTEX_MASK_WIDTH - 1 : 0]       front_src_p_mask_r,
        input                                   front_dst_data_valid,
        input                                   front_any_dst_data_valid,
        input                                   back_stage_vertex_full,

        output                                  buffer_empty,
        output                                  buffer_full,
        output                                  data_valid,
        output [DST_ID_DWIDTH - 1 : 0]          dst_id,
        output [VERTEX_MASK_WIDTH - 1 : 0]      src_p_mask_r,
        output                                  dst_data_valid);

    dst_id_fifo DI1 (
        .clk(clk), .srst(rst),
        .din(front_dst_id), .wr_en(front_any_dst_data_valid), .rd_en(!back_stage_vertex_full),

        .dout(dst_id), .empty(buffer_empty), .prog_full(buffer_full));

    vertex_mask_fifo VM1 (
        .clk(clk), .srst(rst),
        .din(front_src_p_mask_r), .wr_en(front_any_dst_data_valid), .rd_en(!back_stage_vertex_full),

        .dout(src_p_mask_r));

    valid_fifo DDV1 (
        .clk(clk), .srst(rst),
        .din(front_dst_data_valid), .wr_en(front_any_dst_data_valid), .rd_en(!back_stage_vertex_full),

        .dout(dst_data_valid), .valid(data_valid));

endmodule